package zut.wework.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import zut.wework.api.WxApi;
import zut.wework.entity.MsgDomain;
import zut.wework.entity.WxUser;
import zut.wework.entity.ZsjBzks;
import zut.wework.mapper.ZsjBzksMapper;
import zut.wework.service.IZsjBzksService;
import zut.wework.utils.HttpClientUtil;
import zut.wework.utils.JsonUtil;
import zut.wework.utils.RedisUtil;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpSession;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.*;

@Slf4j
@Controller
@RequestMapping("auth")
public class AuthController {
    class Request {
        String serialNo;
        String code;//用户信息要钥匙
        String appId;//应用id
        CompletableFuture<Map<String, Object>> future;
    }

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    WxApi wxApi;
    static String id = "http://baidu.com";
    Map<String, String> urlById = new HashMap<>();

    @PostConstruct
    public void initUrl() {
        urlById.put("1000004", "https://www.baidu.com/");
    }

    //阻塞队列
    LinkedBlockingDeque<Request> deque = new LinkedBlockingDeque<>();


    @PostConstruct
    public void resAuth() {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
        executorService.scheduleAtFixedRate(() -> {
            int size = deque.size();
            if (size == 0) {
                return;
            }
            List<Map<String, String>> params = new ArrayList<>();
            Map<String, Request> serialNoMaps = new HashMap<>();
            for (int i = 0; i < size; i++) {
                Request temp = deque.poll();
                Map<String, String> map = new HashMap<>();
                map.put("serialNo", temp.serialNo);
                map.put("code", temp.code);
                map.put("appId", temp.appId);
                serialNoMaps.put(temp.serialNo, temp);
                params.add(map);
            }
            System.out.println("批量处理数据量：" + size);
            List<Map<String, Object>> responses = getUserInfos(params);


            for (Map<String, Object> res : responses) {
                if (serialNoMaps.containsKey(res.get("serialNo").toString())) {
                    serialNoMaps.get(res.get("serialNo").toString()).future.complete(res);
                    break;
                }
            }

        }, 100, 10, TimeUnit.MILLISECONDS);

    }

    @Autowired
    ZsjBzksMapper zsjBzksMapper;

    @RequestMapping("test")
    public ModelAndView test(@RequestParam(value = "code") String code, @RequestParam(value = "appId") String appId, HttpSession session, ModelAndView modelAndView) throws ExecutionException, InterruptedException {
        if (session.getAttribute("userId") != null) {
            log.info("userid{}", session.getAttribute("userId"));
            WxUser wxUser = JsonUtil.toBean((String) redisUtil.get("userId:" + session.getAttribute("userId")), WxUser.class);
            modelAndView.addObject("userInfo", zsjBzksMapper.selectOne(new QueryWrapper<ZsjBzks>().eq("xh", wxUser.getUserid())));
            modelAndView.setViewName("redirect:" + urlById.get(appId));
        } else if (code != null) {
            String serialNo = UUID.randomUUID().toString();//可以保证请求的唯一
            //CompletableFuture 监听结果线程，相当于futuretask 批量
            CompletableFuture<Map<String, Object>> future = new CompletableFuture<>();
            //绑定业务线程serialNo
            Request request = new Request();
            request.serialNo = serialNo;
            request.code = code;
            request.future = future;
            request.appId = appId;
            deque.add(request);
            Map<String, Object> futureMap = future.get();
            log.info("future:{}", futureMap.toString());
            ZsjBzks zsjBzks = zsjBzksMapper.selectOne(new QueryWrapper<ZsjBzks>().eq("xh", futureMap.get("UserId")));
            redisUtil.set("userId:" + futureMap.get("UserId"), JsonUtil.toJson(zsjBzks));
            if (futureMap.get("error") == null || futureMap.get("error").equals("")) {
                session.setAttribute("userId", futureMap.get("UserId"));
                modelAndView.addObject("userInfo", zsjBzks);
                modelAndView.setViewName("redirect:" + futureMap.get("redirect_url").toString());
            } else {
                log.error("error{}", futureMap.get("error"));
                //不存在 跳转身份验证
                modelAndView.setViewName("/wx/login");
            }
        } else {
            modelAndView.setViewName("wx/msg");
            modelAndView.addObject("msg", new MsgDomain(-1,
                    "错误提示", "我也不知道咋说！"));
        }


        return modelAndView;//没有拿到数据会阻塞，如果拿到类似于futureTast.get
    }

//    public ModelAndView info(ModelAndView modelAndView, WxUser wxUser) {
//
//        return modelAndView;
//    }

    public List<Map<String, Object>> getUserInfos(List<Map<String, String>> maps) {
        List<Map<String, Object>> results = new ArrayList<>();
        for (Map<String, String> item : maps) {
            String getUserInfoUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=" + wxApi.getKeBiaoAccessToken() + "&code=" + item.get("code");
            Map<String, Object> userInfo = new HashMap<>();
            //发送请求获得用户信息
            userInfo = JsonUtil.toMap(HttpClientUtil.get(getUserInfoUrl));
            int errcode = (int) userInfo.get("errcode");
            if (errcode == 0) {
                userInfo.put("redirect_url", urlById.get(item.get("appId")));
                userInfo.put("serialNo", item.get("serialNo"));
            } else {
                userInfo.put("error", "用户不存在");
            }
            results.add(userInfo);
        }

        return results;
    }


}
